<script setup lang="ts">
import { ref, onMounted, reactive, nextTick, computed } from "vue";
import { ElMessage, ElMessageBox, type FormRules, type UploadProps } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import {
  getBannerList,
  deleteBanner,
  createBanner,
  updateBanner,
  getBannerDetail,
  type BannerItem
} from "@/api/banner";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import type { PaginationProps } from "@pureadmin/table";

// 引入图标
import AddFill from "~icons/ri/add-circle-line";
import Delete from "~icons/ep/delete";
import EditPen from "~icons/ep/edit-pen";
import Refresh from "~icons/ep/refresh";
import Search from "~icons/ri/search-line";

defineOptions({
  name: "BannerManagement"
});

const loading = ref(false);
const dataList = ref<BannerItem[]>([]);

// 搜索表单
const searchForm = reactive({
  placement_key: "",
  title: ""
});

// 分页配置
const pagination = reactive<PaginationProps>({
  total: 0,
  pageSize: 10,
  currentPage: 1,
  background: true
});

// 展示位置选项
const placementOptions = [
  { label: "首页顶部轮播", value: "home_top_banner" },
  { label: "首页中部广告位", value: "home_middle_ad" },
  { label: "个人中心广告位", value: "profile_ad" },
  { label: "商城顶部轮播", value: "mall_top_banner" },
  { label: "商品详情页广告", value: "product_detail_ad" }
];

// 跳转类型映射
const linkTypeMap = {
  none: "不跳转",
  webpage: "网页链接",
  miniapp: "小程序页面"
};

// 状态映射
const statusMap = {
  true: { label: "显示", type: "success" },
  false: { label: "隐藏", type: "info" }
};

// 表格列配置
const columns: TableColumnList = [
  {
    label: "ID",
    prop: "id",
    minWidth: 80
  },
  {
    label: "内部标题",
    prop: "title",
    minWidth: 150
  },
  {
    label: "图片预览",
    prop: "image_url",
    minWidth: 150,
    slot: "image"
  },
  {
    label: "展示位置",
    prop: "placement_key",
    minWidth: 150,
    cellRenderer: ({ row }) => {
      const option = placementOptions.find(opt => opt.value === row.placement_key);
      return option?.label || row.placement_key;
    }
  },
  {
    label: "跳转类型",
    prop: "link_type",
    minWidth: 120,
    cellRenderer: ({ row }) => linkTypeMap[row.link_type] || row.link_type
  },
  {
    label: "排序权重",
    prop: "sort_order",
    minWidth: 100,
    sortable: true
  },
  {
    label: "状态",
    prop: "status",
    minWidth: 100,
    slot: "status"
  },
  {
    label: "最后修改时间",
    prop: "updated_at",
    minWidth: 180,
    sortable: true
  },
  {
    label: "操作",
    fixed: "right",
    width: 180,
    slot: "operation"
  }
];

/** 获取列表数据 */
const getList = async () => {
  loading.value = true;
  try {
    const params = {
      page: pagination.currentPage,
      page_size: pagination.pageSize,
      title: searchForm.title || undefined,
      placement_key: searchForm.placement_key || undefined
    };
    const { data } = await getBannerList(params);
    dataList.value = data?.list || [];
    pagination.total = data?.total || 0;
  } catch (error) {
    console.error("获取Banner列表失败:", error);
    ElMessage.error("获取Banner列表失败");
  } finally {
    loading.value = false;
  }
};

/** 搜索 */
const handleSearch = () => {
  pagination.currentPage = 1;
  getList();
};

/** 重置搜索 */
const handleReset = () => {
  searchForm.title = "";
  searchForm.placement_key = "";
  pagination.currentPage = 1;
  getList();
};

// ========== 抽屉表单相关 ==========
const drawerVisible = ref(false);
const drawerTitle = ref("");
const isEdit = ref(false);
const formRef = ref();
const uploading = ref(false);

// 表单数据
const formData = reactive<BannerItem>({
  title: "",
  image_url: "",
  placement_key: "",
  link_type: "none",
  link_target: "",
  sort_order: 0,
  status: false
});

// 跳转类型选项
const linkTypeOptions = [
  { label: "不跳转", value: "none" },
  { label: "网页链接", value: "webpage" },
  { label: "小程序页面", value: "miniapp" }
];

// 表单验证规则
const formRules = reactive<FormRules>({
  title: [{ required: true, message: "请输入内部标题", trigger: "blur" }],
  placement_key: [{ required: true, message: "请选择展示位置", trigger: "change" }],
  image_url: [{ required: true, message: "请上传展示图片", trigger: "change" }],
  link_type: [{ required: true, message: "请选择跳转类型", trigger: "change" }],
  link_target: [
    {
      validator: (rule, value, callback) => {
        if (formData.link_type !== "none" && !value) {
          callback(new Error("请输入跳转目标"));
        } else if (formData.link_type === "webpage" && value) {
          // 验证 URL 格式
          // const urlPattern = /^(http?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
          // if (!urlPattern.test(value)) {
          //   callback(new Error("请输入正确的网页链接"));
          // } else {
          //   callback();
          // }
          callback();
        } else {
          callback();
        }
      },
      trigger: "blur"
    }
  ]
});

// 是否显示跳转目标输入框
const showLinkTarget = computed(() => formData.link_type !== "none");

// 跳转目标输入框的提示文本
const linkTargetPlaceholder = computed(() => {
  if (formData.link_type === "webpage") {
    return "请输入完整的 URL，如：https://www.example.com";
  } else if (formData.link_type === "miniapp") {
    return "请输入小程序页面路径，如：/pages/index/index";
  }
  return "";
});

// 重置表单
const resetForm = () => {
  Object.assign(formData, {
    id: undefined,
    title: "",
    image_url: "",
    placement_key: "",
    link_type: "none",
    link_target: "",
    sort_order: 0,
    status: "published"
  });
  nextTick(() => {
    formRef.value?.clearValidate();
  });
};

/** 新增 Banner */
const handleAdd = () => {
  resetForm();
  isEdit.value = false;
  drawerTitle.value = "新增 Banner";
  drawerVisible.value = true;
};

/** 编辑 Banner */
const handleEdit = async (row: BannerItem) => {
  resetForm();
  isEdit.value = true;
  drawerTitle.value = "编辑 Banner";

  try {
    loading.value = true;
    const { data } = await getBannerDetail(row.id!);
    if (data) {
      Object.assign(formData, data);
    }
    drawerVisible.value = true;
  } catch (error) {
    console.error("获取Banner详情失败:", error);
    ElMessage.error("获取Banner详情失败");
  } finally {
    loading.value = false;
  }
};

/** 删除 Banner */
const handleDelete = async (row: BannerItem) => {
  try {
    await ElMessageBox.confirm(`您确定要删除 Banner"${row.title}"吗？`, "删除确认", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    });

    await deleteBanner(row.id!);
    ElMessage.success("删除成功");
    getList();
  } catch (error) {
    if (error !== "cancel") {
      console.error("删除失败:", error);
      ElMessage.error("删除失败");
    }
  }
};

/** 分页-每页条数改变 */
const handleSizeChange = (val: number) => {
  pagination.pageSize = val;
  getList();
};

/** 分页-当前页改变 */
const handleCurrentChange = (val: number) => {
  pagination.currentPage = val;
  getList();
};

// 图片上传成功
const handleImageSuccess: UploadProps["onSuccess"] = (response, uploadFile) => {
  if (response.code === 200) {
    formData.image_url = import.meta.env.VITE_BASE_URL + response.data.url;
    ElMessage.success("图片上传成功");
    uploading.value = false;
    // 手动触发验证
    formRef.value?.validateField("image_url");
  } else {
    ElMessage.error(response.message || "图片上传失败");
    uploading.value = false;
  }
};

// 图片上传失败
const handleImageError: UploadProps["onError"] = (error, uploadFile) => {
  console.error("图片上传失败:", error);
  ElMessage.error("图片上传失败");
  uploading.value = false;
};

// 图片移除
const handleImageRemove: UploadProps["onRemove"] = () => {
  formData.image_url = "";
  ElMessage.info("图片已移除");
};

// 图片上传前校验
const beforeImageUpload: UploadProps["beforeUpload"] = rawFile => {
  const isJPG = rawFile.type === "image/jpeg" || rawFile.type === "image/png";
  const isLt2M = rawFile.size / 1024 / 1024 < 2;

  if (!isJPG) {
    ElMessage.error("图片只能是 JPG/PNG 格式!");
    return false;
  }
  if (!isLt2M) {
    ElMessage.error("图片大小不能超过 2MB!");
    return false;
  }
  uploading.value = true;
  return true;
};

// 跳转类型改变时，清空跳转目标
const handleLinkTypeChange = () => {
  if (formData.link_type === "none") {
    formData.link_target = "";
  }
  // 触发验证
  formRef.value?.validateField("link_target");
};

// 提交表单
const handleSubmit = async () => {
  const form = formRef.value;
  if (!form) return;

  await form.validate(async valid => {
    if (!valid) return;

    loading.value = true;
    try {
      const submitData = { ...formData };

      if (isEdit.value && formData.id) {
        await updateBanner(formData.id, submitData);
        ElMessage.success("更新成功");
      } else {
        await createBanner(submitData);
        ElMessage.success("创建成功");
      }

      drawerVisible.value = false;
      getList();
    } catch (error) {
      console.error("保存失败:", error);
      ElMessage.error("保存失败");
    } finally {
      loading.value = false;
    }
  });
};

// 关闭抽屉
const handleDrawerClose = () => {
  drawerVisible.value = false;
  resetForm();
};

onMounted(() => {
  getList();
});
</script>

<template>
  <div class="main-content">
    <!-- 搜索表单 -->
    <el-form
      :inline="true"
      :model="searchForm"
      class="search-form bg-bg_color w-full pl-8 pt-[12px] overflow-auto"
    >
      <el-form-item label="标题：" prop="title">
        <el-input
          v-model="searchForm.title"
          placeholder="请输入标题"
          clearable
          class="w-[200px]!"
          @change="handleSearch"
        />
      </el-form-item>
      <el-form-item label="展示位置：" prop="placement_key">
        <el-select
          v-model="searchForm.placement_key"
          placeholder="请选择展示位置"
          clearable
          class="w-[200px]!"
          @change="handleSearch"
        >
          <el-option
            v-for="item in placementOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" :icon="useRenderIcon(Search)" :loading="loading" @click="handleSearch">
          搜索
        </el-button>
        <el-button :icon="useRenderIcon(Refresh)" @click="handleReset"> 重置 </el-button>
      </el-form-item>
    </el-form>

    <!-- 表格 -->
    <PureTableBar title="Banner 管理" :columns="columns" @refresh="getList">
      <template #buttons>
        <el-button type="primary" :icon="useRenderIcon(AddFill)" @click="handleAdd"> 新增 Banner </el-button>
      </template>
      <template v-slot="{ size, dynamicColumns }">
        <pure-table
          adaptive
          :adaptiveConfig="{ offsetBottom: 108 }"
          align-whole="center"
          table-layout="auto"
          :default-sort="{ prop: 'updated_at', order: 'descending' }"
          :loading="loading"
          :size="size"
          :data="dataList"
          :columns="dynamicColumns"
          :pagination="pagination"
          :header-cell-style="{
            background: 'var(--el-fill-color-light)',
            color: 'var(--el-text-color-primary)'
          }"
          @page-size-change="handleSizeChange"
          @page-current-change="handleCurrentChange"
        >
          <!-- 图片预览 -->
          <template #image="{ row }">
            <el-image
              :src="row.image_url"
              :preview-src-list="[row.image_url]"
              fit="cover"
              class="w-[100px] h-[60px] rounded cursor-pointer"
              preview-teleported
            />
          </template>

          <!-- 状态 -->
          <template #status="{ row }">
            <el-tag :type="statusMap[row.status]?.type || 'info'">
              {{ statusMap[row.status]?.label || row.status }}
            </el-tag>
          </template>

          <!-- 操作 -->
          <template #operation="{ row }">
            <el-button
              link
              type="primary"
              :size="size"
              :icon="useRenderIcon(EditPen)"
              @click="handleEdit(row)"
            >
              编辑
            </el-button>
            <el-button
              link
              type="danger"
              :size="size"
              :icon="useRenderIcon(Delete)"
              @click="handleDelete(row)"
            >
              删除
            </el-button>
          </template>
        </pure-table>
      </template>
    </PureTableBar>

    <!-- 抽屉表单 -->
    <el-drawer
      v-model="drawerVisible"
      :title="drawerTitle"
      :before-close="handleDrawerClose"
      direction="rtl"
      size="700px"
      destroy-on-close
    >
      <el-form ref="formRef" v-loading="loading" :model="formData" :rules="formRules" label-width="120px">
        <el-form-item label="内部标题" prop="title">
          <el-input
            v-model="formData.title"
            placeholder="请输入内部标题，用于后台识别"
            maxlength="100"
            show-word-limit
          />
        </el-form-item>

        <el-form-item label="展示位置" prop="placement_key">
          <el-select v-model="formData.placement_key" placeholder="请选择展示位置" class="w-full!">
            <el-option
              v-for="item in placementOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="排序权重" prop="sort_order">
          <el-input-number v-model="formData.sort_order" :min="0" :max="9999" :step="1" class="w-[200px]!" />
          <div class="ml-2 text-sm text-gray-500">数字越小，显示越靠前</div>
        </el-form-item>

        <el-form-item label="状态" prop="status">
          <el-switch v-model="formData.status" />
        </el-form-item>

        <el-form-item label="展示图片" prop="image_url">
          <div class="image-upload-wrapper">
            <!-- 1. 图片上传 -->
            <el-upload
              class="avatar-uploader"
              action="/api/upload-file"
              :show-file-list="false"
              :on-success="handleImageSuccess"
              :on-error="handleImageError"
              :on-remove="handleImageRemove"
              :before-upload="beforeImageUpload"
            >
              <img v-if="formData.image_url" :src="formData.image_url" class="avatar" />
              <el-icon v-else class="avatar-uploader-icon" :class="{ 'is-uploading': uploading }">
                <Plus />
              </el-icon>
            </el-upload>

            <!-- 2. 或者粘贴图片链接 -->
            <div class="mt-3">
              <el-input v-model="formData.image_url" placeholder="或直接输入图片链接地址" clearable>
                <template #prepend>图片链接</template>
              </el-input>
            </div>

            <div class="text-sm text-gray-500 mt-2">
              建议尺寸：750×400px，支持 JPG/PNG 格式，文件大小不超过 2MB
            </div>
          </div>
        </el-form-item>

        <el-form-item label="跳转类型" prop="link_type">
          <el-select
            v-model="formData.link_type"
            placeholder="请选择跳转类型"
            class="w-full!"
            @change="handleLinkTypeChange"
          >
            <el-option
              v-for="item in linkTypeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>

        <el-form-item v-if="showLinkTarget" label="跳转目标" prop="link_target">
          <el-input v-model="formData.link_target" :placeholder="linkTargetPlaceholder" />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="drawer-footer">
          <el-button @click="handleDrawerClose">取消</el-button>
          <el-button type="primary" :loading="loading" @click="handleSubmit"> 保存 </el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<style lang="scss" scoped>
.main-content {
  margin: 24px 24px 0 !important;
}

.search-form {
  :deep(.el-form-item) {
    margin-bottom: 12px;
  }
}

.drawer-footer {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}

.image-upload-wrapper {
  width: 100%;
}

.avatar-uploader .avatar {
  display: block;
  width: 250px;
  height: 178px;
  object-fit: cover;
}

.avatar-uploader .el-upload {
  position: relative;
  overflow: hidden;
  cursor: pointer;
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  width: 178px;
  height: 178px;
  font-size: 28px;
  color: #8c939d;
  text-align: center;
  border: 1px solid #d9d9d9;
}
</style>
